package com.myblog.adkblog.utils;

import com.myblog.adkblog.enums.DataFetcherStrategyEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Component
public class SseUtil implements MessageListener {

    private static final Map<String, SseEmitter> SSE_MAP = new ConcurrentHashMap<>();

    @Autowired
    private RedisTemplate<String ,String> redisTemplate;

    @PostConstruct
    public void init() {
        redisTemplate.getConnectionFactory().getConnection().subscribe(this, "sse-notify".getBytes());
    }

    public SseEmitter createSseEmitter(String clientId) {
        SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);
        SSE_MAP.putIfAbsent(clientId, emitter);

        emitter.onCompletion(() -> SSE_MAP.remove(clientId));
        emitter.onTimeout(() -> SSE_MAP.remove(clientId));
        emitter.onError((e) -> SSE_MAP.remove(clientId));

        pushDataToFront(clientId);
        return emitter;
    }

    public void pushDataToFront(String clientId){
        Object data = DataFetcherStrategyEnum.fuzzyFetcherStrategyEnum(clientId).fetchData(clientId);
        sendData(clientId, data);
    }

    public void sendData(String clientId,Object data){
        SseEmitter emitter = SSE_MAP.get(clientId);
        if (emitter != null) {
            try {
                emitter.send(data);
            } catch (Exception e) {
                SSE_MAP.remove(clientId);
                emitter.completeWithError(e);
            }
        }
    }

    @Override
    public void onMessage(Message message, byte[] bytes) {
        String clientId = new String(message.getBody());
        // 去除消息中的引号
        if (clientId.startsWith("\"") && clientId.endsWith("\"")) {
            clientId = clientId.substring(1, clientId.length() - 1);
        }
        pushDataToFront(clientId);
    }
}
